package org.yangjie.config.security;

import java.util.List;
import java.util.Objects;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import org.yangjie.entity.Role;
import org.yangjie.entity.User;
import org.yangjie.service.RoleService;
import org.yangjie.service.UserService;

/**
 * 用户认证服务实现
 * 
 * 在用户登录的时候，程序将用户输入的的用户名和密码封装成一个类对象。
 * 然后根据用户名去数据库中查找用户的数据，封装成一个类对象放在内存中。
 * 注意，一个是用户输入的数据，一个是数据库中的数据。
 * 将两个对象比对，如果密码正确，就把用户信息的封装（包含着身份信息、细节信息等）
 * 存到SecurityContextHolder中（类似Session），使用的时候还要取出来。
 * 
 * 而这个过程中，从数据库中取出的用户信息的封装不是简单的User实例，而是一个实现了UserDetails这个接口的类的对象，
 * 这个对象里面不仅有用户的账号密码信息，还有一些判断账号是否可用、判断账号是否过期、判断账号是否被锁定的函数。
 * 
 * 在验证过程中，负责根据用户输入的用户名返回数据库中用户信息的封装这个功能的就是Service，
 * 它实现了UserDetailsService，重写了它的loadUserByUsername(String s)方法，这个方法就是根据用户名返回了UserDetails的一个具体实现。
 * 
 * @author YangJie [2019年1月17日]
 */
@Component
public class UserDetailsServiceImpl implements UserDetailsService{
	
	@Autowired
	private UserService userService;
	@Autowired
	private RoleService roleService;

	
	@Override // 认证用户配置
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		if(Objects.isNull(username) || username.trim().isEmpty()) {
			throw new UsernameNotFoundException("用户名非法");
		}
		User user = userService.getByUsername(username);
		if(Objects.isNull(user) || user.getId()<=0) {
			throw new UsernameNotFoundException("用户名不存在");
		}
		// 当前用户角色/权限列表
		List<Role> roleList = roleService.getListByUserId(user.getId());
		// 也可以使用spring自带的UserDetails实现类: org.springframework.security.core.userdetails.User
		return new UserDetailsImpl(user, roleList);
	}

}
